package pl.poznan.put.cs.idss.viamdp.core.structures;

/**
 * Klasa mapy - utrzymuje tablice pól i obrazuje stan w świata.
 * 
 * @author Kornel Lewandowski
 * 
 */
public class Map {

	private IField[][] fieldsArray;

	private int sizeX = 0;
	private int sizeY = 0;

	private long iteration = 1;

	private double correctMoveProbability = 1.0;
	private double turnLeftMoveProbability = 0.0;
	private double turnRightMoveProbability = 0.0;
	private double goBackMoveProbability = 0.0;
	private double indifferenceThreshold = 0.001;

	private double moveReward = -0.04;

	private double terminalFieldValue = 1.0;
	private double holeFieldValue = -1.0;

	private double discountValue = 0.9;

	public Map(final int sizeX, final int sizeY) {

		this.fieldsArray = new IField[sizeX][sizeY];

		this.sizeX = sizeX;
		this.sizeY = sizeY;

	}

	public void setAvailableField(int x, int y, double startReward) {

		AvailableField currentField = new AvailableField(x, y, this);
		currentField.setRewardValue(startReward);
		getFieldsArray()[x][y] = currentField;

	}

	public void setTerminalField(int x, int y) {

		TerminalField currentField = new TerminalField(x, y, this);
		currentField.setRewardValue(terminalFieldValue);
		getFieldsArray()[x][y] = currentField;

	}

	public void setHoleField(int x, int y) {

		HoleField currentField = new HoleField(x, y, this);
		currentField.setRewardValue(holeFieldValue);
		getFieldsArray()[x][y] = currentField;

	}

	public void setForbiddenField(int x, int y) {

		ForbiddenField currentField = new ForbiddenField(x, y, this);
		currentField.setRewardValue(Double.MIN_NORMAL);
		getFieldsArray()[x][y] = currentField;

	}

	public int getSizeX() {
		return sizeX;
	}

	public void setSizeX(int sizeX) {
		this.sizeX = sizeX;
	}

	public int getSizeY() {
		return sizeY;
	}

	public void setSizeY(int sizeY) {
		this.sizeY = sizeY;
	}

	public long getIteration() {
		return iteration;
	}

	public void setIteration(long iteration) {
		this.iteration = iteration;
	}

	public void incrementIteration() {
		iteration += 1;
	}

	public double getCorrectMoveProbability() {
		return correctMoveProbability;
	}

	public void setCorrectMoveProbability(double correctMoveProbability) {
		this.correctMoveProbability = correctMoveProbability;
	}

	public double getTurnLeftMoveProbability() {
		return turnLeftMoveProbability;
	}

	public void setTurnLeftMoveProbability(double turnLeftMoveProbability) {
		this.turnLeftMoveProbability = turnLeftMoveProbability;
	}

	public double getTurnRightMoveProbability() {
		return turnRightMoveProbability;
	}

	public void setTurnRightMoveProbability(double turnRightMoveProbability) {
		this.turnRightMoveProbability = turnRightMoveProbability;
	}

	public double getGoBackMoveProbability() {
		return goBackMoveProbability;
	}

	public void setGoBackMoveProbability(double goBackMoveProbability) {
		this.goBackMoveProbability = goBackMoveProbability;
	}

	public double getIndifferenceThreshold() {
		return indifferenceThreshold;
	}

	public void setIndifferenceThreshold(double indifferenceThreshold) {
		this.indifferenceThreshold = indifferenceThreshold;
	}

	public double getTerminalFieldValue() {
		return terminalFieldValue;
	}

	public void setTerminalFieldValue(double terminalFieldValue) {
		this.terminalFieldValue = terminalFieldValue;
	}

	public double getHoleFieldValue() {
		return holeFieldValue;
	}

	public void setHoleFieldValue(double holeFieldValue) {
		this.holeFieldValue = holeFieldValue;
	}

	public double getMoveReward() {
		return moveReward;
	}

	public void setMoveReward(double moveReward) {
		this.moveReward = moveReward;
		this.indifferenceThreshold = Math.abs(this.moveReward / 1000);
	}

	public double getDiscountValue() {
		return discountValue;
	}

	public void setDiscountValue(double discountValue) {
		this.discountValue = discountValue;
	}

	public void printMapAsText() {

		System.out.println();

		System.out.println(iteration + ". iteracja");

		for (int i = 0; i < sizeX; i++) {
			for (int j = 0; j < sizeY; j++) {
				if (getFieldsArray()[i][j] != null) {
					System.out.print(getFieldsArray()[i][j].toString() + "\t");
				}
			}
			System.out.println();
		}

	}

	public IField[][] getFieldsArray() {
		return fieldsArray;
	}

}
